package helper.scxml.scxml2.t0.case1_cycle.zone

import helper.base.A2LHM
import helper.base.ConstraintHelper.CompareOp.Companion.geOp
import helper.base.ConstraintHelper.CompareOp.Companion.lOp
import helper.base.ConstraintHelper.CompareOp.Companion.leOp
import helper.base.ConstraintHelper.CompositeConstraint.Expand.toW1N2Constraint
import helper.base.ConstraintHelper.W1N1N2ConstraintHelper.getV1Constraint
import helper.base.ConstraintHelper.W1N2Constraint
import helper.base.LHMHelper.A4LHM
import helper.scxml.scxml2.t0.case1_cycle.zone.ZoneStrategyHelper.AgentZoneStrategy.Companion.getAgentZoneStrategy
import helper.scxml.scxml2.t0.case1_cycle.zone.ZoneStrategyHelper.TotalZoneStrategy.Companion.getType1Type1TotalZoneStrategy
import helper.scxml.scxml2.zone.t2.ConfigHelper.Config.Companion.makeConfig
import org.junit.Test

class ZoneStrategyHelperTest {
    @Test
    fun t1t1() {
        val sb = StringBuilder()
        val stringConstraintLHM = A2LHM<String, W1N2Constraint>().also {
            it["0<=x<90"] = getV1Constraint("x", geOp, 0, lOp, 90)
            it["90<=x<100"] = getV1Constraint("x", geOp, 90, lOp, 100)
            it["100<=x<=100"] = getV1Constraint("x", geOp, 100, leOp, 100)
            it["0<=x<100"] = getV1Constraint("x", geOp, 0, lOp, 100)
            it["90<=x<=100"] = getV1Constraint("x", geOp, 90, leOp, 100)
            it["0<=x<=100"] = getV1Constraint("x", geOp, 0, leOp, 100)
            it["60<=x<=120"] = getV1Constraint("x", geOp, 60, leOp, 120)
            it["20<=x<=140"] = getV1Constraint("x", geOp, 20, leOp, 140)
            it["0<=x<=0"] = getV1Constraint("x", geOp, 0, leOp, 0)
        }
        stringConstraintLHM.map {
            sb.append("${it.value}\n")
        }
        val rs = sb.toString().trim()
        println(rs)
        assert(
            rs == """
                0.0<=x<90.0
                90.0<=x<100.0
                100.0<=x<=100.0
                0.0<=x<100.0
                90.0<=x<=100.0
                0.0<=x<=100.0
                60.0<=x<=120.0
                20.0<=x<=140.0
                0.0<=x<=0.0
            """.trimIndent()
        )
    }

    @Test
    fun t1t2() {
        val arrayOf = arrayOf(
            "0.0<=x<90.0",
            "90.0<=x<100.0",
            "100.0<=x<=100.0",
            "0.0<=x<100.0",
            "90.0<=x<=100.0",
            "0.0<=x<=100.0",
            "60.0<=x<=120.0",
            "20.0<=x<=140.0",
            "0.0<=x<=0.0",
        )
        val sb = StringBuilder()
        arrayOf.map {
            val c = it.toW1N2Constraint()
            sb.append("${c}\n")
        }
        val rs = sb.toString().trim()
        println(rs)
        assert(
            rs == """
                0.0<=x<90.0
                90.0<=x<100.0
                100.0<=x<=100.0
                0.0<=x<100.0
                90.0<=x<=100.0
                0.0<=x<=100.0
                60.0<=x<=120.0
                20.0<=x<=140.0
                0.0<=x<=0.0
            """.trimIndent()
        )
    }

    @Test
    fun t2() {
        val envZS = getAgentZoneStrategy(A4LHM<String, String, String, Double>().also { lhm ->
            lhm.addIfAbsent("s0", "0<=x<=100", "s0s1", 1.0)
            lhm.addIfAbsent("s1", "90<=x<=100", "s1s4t2", 1.0)
        })
        val renZS = getAgentZoneStrategy(A4LHM<String, String, String, Double>().also { lhm ->
            "0<=x<100".let {
                lhm.addIfAbsent("s1", it, "s1s2", 1.0)
                lhm.addIfAbsent("s1", it, "s1s3", 1.0)
            }
            "100<=x<=100".let {
                lhm.addIfAbsent("s1", it, "s1s2", 1.0)
                lhm.addIfAbsent("s1", it, "s1s3", 1.0)
                lhm.addIfAbsent("s1", it, "s1s4t1", 1.0)
            }
        })

        val totalZoneStrategy = getType1Type1TotalZoneStrategy(
            envZS,
            renZS,
        )
        // 运行 selectEvent 函数 100000 次
        val times = 21400000
        val eventCounts = hashMapOf<String, Int>()
        repeat(times) {
            val (_, event) = totalZoneStrategy.getMTimeEventChoice(
                makeConfig(
                    "s1",
                )
            )
            eventCounts[event] = eventCounts.getOrDefault(event, 0) + 1
        }

        // 打印每个事件被选中的次数
        eventCounts.forEach { (event, count) ->
            println("Event $event: \t$count times")
        }
    }
}